package com.cl.photozoom.gestures;

import android.content.Context;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;

public class CupcakeGestureDetector implements GestureDetector {

    protected OnGestureListener mListener; 
    
    float mLastTouchX;
    
    float mLastTouchY;
    
    final float mTouchSlop;
    
    final float mMinimumVelocity;

    @Override
    public void setOnGestureListener(OnGestureListener listener) {
    	
        this.mListener = listener;
        
    }

    public CupcakeGestureDetector(Context context) {
    	
        final ViewConfiguration configuration = ViewConfiguration.get(context);
        
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
        
        mTouchSlop = configuration.getScaledTouchSlop();
        
    }

    private VelocityTracker mVelocityTracker;
    
    private boolean mIsDragging;

    float getActiveX(MotionEvent ev) {
    	
    	try {
        	
            return ev.getX();
			
		} catch (Exception e) { 
			
			return 0;
		}
        
    }

    float getActiveY(MotionEvent ev) {
    	
    	try {
        	
            return ev.getY();
			
		} catch (Exception e) { 
			
			return 0;
		}
        
    }

    @Override
    public boolean isScaling() {
    	
        return false;
        
    }

    @Override
    public boolean isDragging() {
    	
        return mIsDragging;
        
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
    	
    	try {
    		
            switch (ev.getAction()) {
            
            case MotionEvent.ACTION_DOWN: {
            	
                mVelocityTracker = VelocityTracker.obtain();
                
                if (null != mVelocityTracker) {
                	
                    mVelocityTracker.addMovement(ev);
                    
                }

                mLastTouchX = getActiveX(ev);
                
                mLastTouchY = getActiveY(ev);
                
                mIsDragging = false;
                
                break;
                
            }

            case MotionEvent.ACTION_MOVE: {
            	
                final float x = getActiveX(ev);
                
                final float y = getActiveY(ev);
                
                final float dx = x - mLastTouchX, dy = y - mLastTouchY;

                if (!mIsDragging) {
                	
                    mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
                    
                }

                if (mIsDragging) {
                	
                    mListener.onDrag(dx, dy);
                    
                    mLastTouchX = x;
                    
                    mLastTouchY = y;

                    if (null != mVelocityTracker) {
                    	
                        mVelocityTracker.addMovement(ev);
                        
                    }
                    
                }
                
                break;
                
            }

            case MotionEvent.ACTION_CANCEL: { 
            	
                if (null != mVelocityTracker) {
                	
                    mVelocityTracker.recycle();
                    
                    mVelocityTracker = null;
                    
                }
                
                break;
            }

            case MotionEvent.ACTION_UP: {
            	
                if (mIsDragging) {
                	
                    if (null != mVelocityTracker) {
                    	
                        mLastTouchX = getActiveX(ev);
                        
                        mLastTouchY = getActiveY(ev);
 
                        mVelocityTracker.addMovement(ev);
                        
                        mVelocityTracker.computeCurrentVelocity(1000);

                        final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker.getYVelocity();
 
                        if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
                        	
                            mListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);
                            
                        }
                        
                    }
                    
                }
 
                if (null != mVelocityTracker) {
                	
                    mVelocityTracker.recycle();
                    
                    mVelocityTracker = null;
                    
                }
                
                break;
                
            }
            
    	}
			
		} catch (Exception e) {} 

        return true;
        
    }
    
}
